#include "contenttype.h"
#include "mail.h"


MAIL*
mail_new(const char *filename, const char *bpath)
{
    MAIL    *mail;

    mail = (MAIL*)emalloc(sizeof(MAIL));
    if (NULL == mail) {
        ERROR("mail_new: malloc MAIL error!\n");
        return NULL;
    }
    memset(mail, 0, sizeof(MAIL));
	mail->buffer = buf_new(4096, filename, 0);
	if (NULL == mail->buffer) {
		efree(mail);
        ERROR("mail_new: malloc BUFFER error!\n");
		return NULL;
	}    

    mail->MailHead = mailhead_new();
    if (NULL == mail->MailHead) {
        buf_delete(mail->buffer);
        efree(mail);
        ERROR("mail_new: malloc MAILHEAD error!\n");
        return NULL;
    }

    mail->basepath = xstrdup(bpath);

    return mail;
}


void
mail_delete(MAIL* mail)
{
	GSList	*slist, *tmp;
    if (NULL == mail)
        return;
    
	buf_delete(mail->buffer);
	
    mail_clear(mail);
    mailhead_delete(mail->MailHead);

    efree(mail);
}

void mailmime_delete (gpointer data, gpointer user_data)
{
     MIME   *m = (MIME*)data;
     mime_delete(m);
}

void
mail_clear(MAIL* mail)
{
    if (NULL == mail)
        return;

    if (NULL != mail->MailHead) {
        mailhead_delete(mail->MailHead);
        mail->MailHead = NULL;
    }    

    if (NULL != mail->MailMime) {
        g_slist_foreach(mail->MailMime, mailmime_delete, NULL);
        g_slist_free(mail->MailMime);
        mail->MailMime = NULL;
    }
    
    SAFE_FREE(mail->basepath)
}

void boundary_key_destroy(gpointer data)
{
    efree(data);
}

void boundary_value_destroy(gpointer data)
{
}

int
mail_parse(MAIL* mail, int is_parse_data)
{
    int         ret, i;
    BUFFER      *buf;
    char        *start;
    int         len = 0;
    MIME        *mime, *other;
    char        *ptr;
    GSList      *slist = NULL;
    GHashTable  *boundary;
    char        *type;
    CONTENT_TYPE *ctype;
    char        *mainbound = NULL;
    int         mimecount = 0; // mime部分的数量

    buf = mail->buffer;
	if (NULL == mail) {
        ERROR("mail_parse: parameter mail is NULL\n");
		return -1;
    }
   
    boundary = g_hash_table_new_full(g_str_hash, g_str_equal, boundary_key_destroy, NULL);
    if (NULL == boundary) {
        return -2;
    }

    // 不管是head部分还是mime部分，都是只传递开始的位置进去，结束需要在里面自己确定
    INFO("parse mailhead ...\n");
    ret = mailhead_parse(mail->MailHead, mail->buffer);
    INFO("mailhead ret=%d\n", ret);
    if (ret < 0)
        goto mail_parse_return_pos;
  
    type = g_hash_table_lookup(mail->MailHead->Others, "content-type");
    if (NULL != type) {
        ctype = contenttype_new();
        INFO("parse content-type: %s\n", type);
       
        contenttype_parse(ctype, type);
        contenttype_print(ctype);
        if (ctype->Boundary) {
            xstrnlower(ctype->Boundary, strlen(ctype->Boundary));
            mainbound = xstrdup(ctype->Boundary);
            xstrnlower(mainbound, strlen(mainbound));
            INFO("mainbound: %s, len: %d, hash: %u\n", mainbound, strlen(mainbound), g_str_hash(mainbound));
            g_hash_table_insert(boundary, mainbound, mainbound);
        }
        contenttype_delete(ctype);
    }
    while (1) {
        // 取的是head的空行之后的第一个字符
        start = &buf->data[buf->pos];             
        if (0 == *start) {
            break;
        }
        INFO("start: %c%c%c %d.%d.%d\n", *start, *(start+1), *(start+2), *start, *(start+1), *(start+2));
        if (*start != '\r' && *start != '\n') { // 不是换行符，那么就是数据了
            mime = mime_new(mail->basepath);
            if (NULL == mime) {
                ret = -2;
                break;
            }

            if (*start == '-' && *(start+1) == '-') {
                int blen;
                INFO("start with -- ... len:%d\n", len);
                // 如果是--, 那么在buffer里下次才会读到，应该先读出来，mime_parse里第一次读就应该是读到mime头部
                blen = xstrslen(start, "\r\n", 2);
                if (start[blen-1] == '-') { // boundary的最后字符是--说明后面没有紧跟数据
                    ret = buf_getline(buf, &start, &len);
                    if (ret == 0) { // 信息结束
                        break;
                    }

                    mime_delete(mime);
                    continue;
                }

                ret = buf_getline(buf, &start, &len);
                if (ret == 0) { // 信息结束
                    break;
                }
                
                mime->HeadStart = buf_file_pos(mail->buffer) - len;
                ret = mime_parse(mime, mail->buffer, is_parse_data, 1, boundary);
                if (ret < 0)
                    break;
            }else{
                INFO("start with data. ..\n");
                if (NULL != mainbound) {
                    mime->boundary = xstrdup(mainbound);  // 内存泄露??
                    INFO("boundary: %p\n", mime->boundary);
                }
                //g_hash_table_insert(boundary, mainbound, mime);
                // 开头不是-- 那么这个数据部分可能是紧跟在head后的，它的描述就是在head里，应该复制过来
                mime->HeadStart = 0;
                mime->HeadLen = 0;
                ptr = g_hash_table_lookup(mail->MailHead->Others, "mime-version");
                if (NULL != ptr) {
                    mime->MimeVersion = xstrdup(ptr);
                }
                ptr = g_hash_table_lookup(mail->MailHead->Others, "content-type");
                if (NULL != ptr) {
                    mime->ContentType = xstrdup(ptr);
                    mime->ctype = check_maintype(mime->ContentType);
                }
                ptr = g_hash_table_lookup(mail->MailHead->Others, "content-transfer-encoding");
                if (NULL != ptr) {
                    mime->ContentTransferEncoding = xstrdup(ptr);
                }
                ptr = g_hash_table_lookup(mail->MailHead->Others, "content-id");
                if (NULL != ptr) {
                    mime->ContentId = xstrdup(ptr);
                }
                ptr = g_hash_table_lookup(mail->MailHead->Others, "content-disposition");
                if (NULL != ptr) {
                    mime->ContentDisposition = xstrdup(ptr);
                }
                ret = mime_parse(mime, mail->buffer, is_parse_data, 0, boundary);
                if (ret < 0)
                    break;
            }
            INFO("current mime!\n");
            mime_print(mime);
            // 添加到链表上的时候必须保证第一项是text, 第二项是html
            if (NULL != mime->ContentType) {
                if (strstr(mime->ContentType, "text/plain") != NULL) {
                    mail->MailMime = g_slist_prepend(mail->MailMime, mime);
                }else if (strstr(mime->ContentType, "text/html") != NULL) {
                    slist = g_slist_nth(mail->MailMime, 0);
                    if (NULL != slist) { 
                        other = slist->data;
                        if (NULL != other->ContentType && strstr(other->ContentType, "text/plain") != NULL) {
                            mail->MailMime = g_slist_insert(mail->MailMime, mime, 1);
                        }else{
                            mail->MailMime = g_slist_prepend(mail->MailMime, mime);
                        }
                    }else{
                        mail->MailMime = g_slist_prepend(mail->MailMime, mime);
                    }
                }else{
                    mail->MailMime = g_slist_append(mail->MailMime, mime);
                }
            }else{
                mail->MailMime = g_slist_append(mail->MailMime, mime);
            }
        }else{
            ret = buf_getline(buf, &start, &len);
            INFO("getline: %d\n", ret);
            if (ret == 0) { // 信息结束
                break;
            }
        }

    }
    
    INFO("mime length: %d, ret: %d\n", g_slist_length(mail->MailMime), ret);

mail_parse_return_pos:
    g_hash_table_destroy(boundary);
    return ret;
}

int 
mail_string(MAIL *mail, char *save, int slen)
{
    if (NULL == mail)
        return -1;

    
    return 0;
}




